﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace DatabaseUserTest.Model
{
    public class Graph : IEnumerable
    {
        private List<GraphNode> nodeSet;

        public Graph() : this(null) { }
        public Graph(List<GraphNode> nodeSet)
        {
            if (nodeSet == null)
                this.nodeSet = new List<GraphNode>();
            else
                this.nodeSet = nodeSet;
        }
        public void AddNode(GraphNode node)
        {
            if (!this.Contains(node.NodeName))
            {
                nodeSet.Add(node);
            }
        }
        public void AddNode(string value)
        {
            this.AddNode(new GraphNode(value));
        }
        public void AddDirectedEdge(string from, string to)
        {
            AddDirectedEdge(from, to, 0);
        }
        public void AddDirectedEdge(GraphNode from, GraphNode to)
        {
            AddDirectedEdge(from, to, 0);
        }
        public void AddDirectedEdge(GraphNode from, GraphNode to, double cost)
        {
            from.Neighbors.Add(to);
            from.Costs.Add(cost);
        }
        public void AddDirectedEdge(string from, string to, double cost)
        {
            GraphNode fromnode = nodeSet.Find((x) => { return x.NodeName.Contains(from); });
            GraphNode tonode = nodeSet.Find((x) => { return x.NodeName.Contains(to); });
            fromnode.Neighbors.Add(tonode);
            fromnode.Costs.Add(cost);

        }



        public GraphNode FindNode(string value)
        {
            GraphNode node = nodeSet.Find((x) => { return x.NodeName.Contains(value); });
            if (node == null)
            {
                throw new NullReferenceException();
            }
            return node;
        }

        public void Clear()
        {
            nodeSet.Clear();
        }
        public bool Contains(string value)
        {
            return nodeSet.Find((x) => { return x.NodeName.Equals(value); }) != null;
        }
        public bool Remove(string value)
        {
            GraphNode  nodeToRemove = (GraphNode)nodeSet.Find((x) => { return x.NodeName.Equals(value); });
            if (nodeToRemove == null)
                return false;

            nodeSet.Remove(nodeToRemove);

            foreach (GraphNode  gnode in nodeSet)
            {
                int index = gnode.Neighbors.IndexOf(nodeToRemove);
                if (index != -1)
                {
                    gnode.Neighbors.RemoveAt(index);
                    gnode.Costs.RemoveAt(index);
                }
            }

            return true;
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.nodeSet.GetEnumerator();
        }
        public override string ToString()
        {
            string s = "";
            foreach (GraphNode  x in this)
            {
                s += "(" + x.ToString() + ") ";
            }
            return s;
        }
        public List<GraphNode > Nodes
        {
            get
            {
                return nodeSet;
            }
        }

        public int Count
        {
            get { return nodeSet.Count; }
        }
    }
}